package txvod;

import com.alibaba.fastjson.JSONObject;
import com.qcloud.vod.VodUploadClient;
import com.qcloud.vod.model.VodUploadRequest;
import com.qcloud.vod.model.VodUploadResponse;
import com.tencentcloudapi.common.Credential;
import com.tencentcloudapi.common.exception.TencentCloudSDKException;
import com.tencentcloudapi.common.profile.ClientProfile;
import com.tencentcloudapi.common.profile.HttpProfile;
import com.tencentcloudapi.vod.v20180717.VodClient;
import com.tencentcloudapi.vod.v20180717.models.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Component;
import org.springframework.util.Assert;

import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * txvod
 *
 * @description:
 * @author: yechen
 * @email: wangqingfeng@wxyundian.com
 * @date: 2020年10月08日 10:35
 */
@Component
@Slf4j
public class TxVodCaller {
    private static String secretId = "AKID94lBKUOt8P8cpqtaBVY0B5i8nEOOddsq";
    private static String secretKey = "83pL4WicOBhz0mIuGL9hz1n9EzUihurZ";
    private static VodUploadClient vodUploadClient;
    private static Credential cred;
    private static VodClient vodClient;

    private static Long subAppId = 1259097831L;
    private static String endPoint = "vod.tencentcloudapi.com";
    //云点播支持的视频类型，了解地址：https://cloud.tencent.com/document/product/266/9760#.E6.96.87.E4.BB.B6.E7.B1.BB.E5.9E.8B
    private final static String[] VIDEO_TYPE = {"MP4", "TS", "FLV", "WMV", "ASF", "RM", "RMVB", "MPG", "MPEG", "3GP", "MOV", "WEBM", "MKV", "AVI"};
    //云点播支持的封面图片类型，了解地址：https://cloud.tencent.com/document/product/266/9760#.E6.96.87.E4.BB.B6.E7.B1.BB.E5.9E.8B
    private final static String[] COVER_IMAGE_TYPE = {"JPG", "JPEG", "PNG", "GIF", "BMP", "TIFF", "AI", "CDR", "EPS"};
    //云点播支持的音频类型，了解地址：https://cloud.tencent.com/document/product/266/9760#.E6.96.87.E4.BB.B6.E7.B1.BB.E5.9E.8B
    private final static String[] VOICE_TYPE = {"MP3", "M4A", "FLAC", "OGG", "WAV"};

    private final static String VIDEO_INPUT_TYPE_FILE = "File";
    private final static String VIDEO_INPUT_TYPE_STREAM = "Stream";

    //云点播处理视频任务-状态过程
    private final static String TASK_STATUS_WAITING = "WAITING";
    private final static String TASK_STATUS_PROCESSING = "PROCESSING";
    private final static String TASK_STATUS_FINISH = "FINISH";


    static {
        vodUploadClient = new VodUploadClient(secretId, secretKey);
        cred = new Credential(secretId, secretKey);

        HttpProfile httpProfile = new HttpProfile();
        httpProfile.setEndpoint(endPoint);
        ClientProfile clientProfile = new ClientProfile();
        clientProfile.setHttpProfile(httpProfile);
        vodClient = new VodClient(cred, "", clientProfile);
    }

    /***
     * java 客户端上传--2020年10月8日14:30:45
     *
     * @param fileInput
     */
    public static void uploadVideo(File fileInput) {
        if (null == fileInput || !fileInput.exists()) {
            throw new RuntimeException("源视频文件不存在，请检查源视频路径");
        }
        String format = getFormat(fileInput);
        if (!isLegalFormat(format)) {
            throw new RuntimeException("无法解析的视频格式：" + format);
        }
        VodUploadRequest request = new VodUploadRequest();
        request.setMediaFilePath(fileInput.getPath());
        request.setSubAppId(subAppId);
        try {
            long start = System.currentTimeMillis();
            VodUploadResponse response = vodUploadClient.upload("ap-chongqing", request);
            log.info("<<<<<<<<<<上传视频结束，共消耗{} ms, FileId = {}, resp:{}", System.currentTimeMillis() - start, response.getFileId(), JSONObject.toJSONString(response));
        } catch (Exception e) {
            // 业务方进行异常处理
            log.error("Upload Err", e);
        }
    }

    /***
     * 视频源地址--上传方式
     *
     * @param videoUrl
     * @return
     */
    public static PullUploadResponse uploadVideoByUrl(String videoUrl) {
        if (StringUtils.isBlank(videoUrl)) {
            throw new RuntimeException("源视频文件不存在，请检查源视频路径");
        }
        String format = videoUrl.substring(videoUrl.lastIndexOf(".") + 1);
        if (!isLegalFormat(format)) {
            throw new RuntimeException("无法解析的视频格式：" + format);
        }
        try {
            PullUploadRequest req = new PullUploadRequest();
            req.setMediaUrl(videoUrl);

            long start = System.currentTimeMillis();
            PullUploadResponse resp = vodClient.PullUpload(req);
            log.info("<<<<<<<<<<上传视频结束，共消耗{} ms, resp:{}", System.currentTimeMillis() - start, JSONObject.toJSONString(resp));
            return resp;
        } catch (TencentCloudSDKException e) {
            // 业务方进行异常处理
            log.error("上传视频 Err", e);
        }
        return null;
    }

    /***
     * 根据上传结果返回的任务id查询任务详情---采用mq消费模式轮询
     *
     * @param taskId
     */
    public static DescribeTaskDetailResponse queryTaskDetailByUrl(String taskId) {
        try {
            long start = System.currentTimeMillis();
            DescribeTaskDetailRequest taskDetailRequest = new DescribeTaskDetailRequest();
            taskDetailRequest.setSubAppId(subAppId);
            taskDetailRequest.setTaskId(taskId);
            DescribeTaskDetailResponse taskDetailResponse = vodClient.DescribeTaskDetail(taskDetailRequest);
            log.info("<<<<<<<<<<查询视频任务详情，共消耗{} ms, resp:{}", System.currentTimeMillis() - start, JSONObject.toJSONString(taskDetailResponse));
            return taskDetailResponse;
        } catch (TencentCloudSDKException e) {
            // 业务方进行异常处理
            log.error("查询视频任务详情 Err", e);
        }
        return null;
    }

    /***
     * 编辑视频
     * @param fileId 视频的 ID。
     * @param StartTimeOffset 视频剪辑的起始偏移时间偏移，单位：秒。
     * @param EndTimeOffset 视频剪辑的起始结束时间偏移，单位：秒。
     */
    /***
     * 编辑视频
     *
     * @param inputType 输入视频的类型，可以取的值为 File，Stream 两种。
     * @param fileInfos 输入的视频文件信息，当 InputType 为 File 时必填。
     * @param streamInfos 输入的流信息，当 InputType 为 Stream 时必填。
     */
    public static EditMediaResponse editVideo(String inputType, EditMediaFileInfo[] fileInfos, EditMediaStreamInfo[] streamInfos) {
        if (StringUtils.isBlank(inputType)) {
            throw new RuntimeException("请传值-输入视频的类型，可以取的值为 File，Stream 两种");
        }
        try {
            EditMediaRequest req = new EditMediaRequest();
            //输入视频的类型，可以取的值为 File，Stream 两种，了解地址：https://cloud.tencent.com/document/product/266/34783
            req.setInputType(inputType);
            if (VIDEO_INPUT_TYPE_FILE.equals(inputType)) {
                req.setFileInfos(fileInfos);
            } else if (VIDEO_INPUT_TYPE_STREAM.equals(inputType)) {
                //该场景比较适用于
                req.setStreamInfos(streamInfos);
            } else {
                throw new RuntimeException("输入视频的类型，可以取的值为 File，Stream 两种");
            }
            long start = System.currentTimeMillis();
            EditMediaResponse resp = vodClient.EditMedia(req);
            log.info("<<<<<<<<<<编辑视频处理，共消耗{} ms, resp:{}", System.currentTimeMillis() - start, JSONObject.toJSONString(resp));
            return resp;
        } catch (TencentCloudSDKException e) {
            // 业务方进行异常处理
            log.error("<<<<<<<<<<编辑视频处理 Err", e);
        }
        return null;
    }

    /***
     * 删除媒体
     *
     * @param fileId
     * @return
     */
    public static DeleteMediaResponse deleteMedia(String fileId) {
        log.info("<<<<<<<<<<删除视频处理，fileId={}", fileId);
        long start = System.currentTimeMillis();
        DeleteMediaRequest req = new DeleteMediaRequest();
        req.setFileId(fileId);
        req.setSubAppId(subAppId);
        try {
            DeleteMediaResponse resp = vodClient.DeleteMedia(req);
            log.info("<<<<<<<<<<删除视频处理，共消耗{} ms, resp:{}", System.currentTimeMillis() - start, JSONObject.toJSONString(resp));
            return resp;
        } catch (TencentCloudSDKException e) {
            // 业务方进行异常处理
            log.error("<<<<<<<<<<删除视频处理 Err", e);
        }
        return null;
    }

    /***
     * 获取媒体信息
     *
     * @param fileIds
     * @return
     */
    public static DescribeMediaInfosResponse mediaDetail(List<String> fileIds) {
        log.info("<<<<<<<<<<查询视频详情处理，fileIds={}", fileIds);
        long start = System.currentTimeMillis();
        DescribeMediaInfosRequest req = new DescribeMediaInfosRequest();
        req.setFileIds(fileIds.toArray(new String[0]));
        req.setSubAppId(subAppId);
        try {
            DescribeMediaInfosResponse resp = vodClient.DescribeMediaInfos(req);
            log.info("<<<<<<<<<<查询视频详情处理，共消耗{} ms, resp:{}", System.currentTimeMillis() - start, JSONObject.toJSONString(resp));
            return resp;
        } catch (TencentCloudSDKException e) {
            // 业务方进行异常处理
            log.error("<<<<<<<<<<查询视频详情处理 Err", e);
        }
        return null;
    }


    /**
     * 获取指定文件的后缀名
     *
     * @param file
     * @return
     */
    private static String getFormat(File file) {
        String fileName = file.getName();
        return fileName.substring(fileName.indexOf(".") + 1);
    }

    /**
     * 检测视频格式是否合法
     *
     * @param format
     * @return
     */
    private static boolean isLegalFormat(String format) {
        List<String> videoList = Arrays.asList(VIDEO_TYPE);
        List<String> voiceList = Arrays.asList(VOICE_TYPE);
        List<String> formatList = new ArrayList<>(videoList);
        formatList.addAll(voiceList);

        for (String item : formatList) {
            if (item.equals(StringUtils.upperCase(format))) {
                return true;
            }
        }
        return false;
    }


//    public static void main(String[] args) {
//        //1.75g视频
//        String video_1_75g = "https://cdn-school.jikemofang.com/class/video/%E9%98%B3%E5%85%89%E7%94%B5%E5%BD%B1wwwygdy8com%E5%8D%B1%E9%99%A9%E7%9A%84%E8%B0%8E%E8%A8%80BD1080p%E4%B8%AD%E8%8B%B1%E5%8F%8C%E5%AD%97%E5%B9%95-1602146164527.mp4";
//        //小视频
//        String video_short = "https://cdn-school.jikemofang.com/class/video/%E9%9B%86%E5%AE%A2%E5%B0%8F%E5%BA%97%E7%B2%89%E4%B8%9D%E4%BD%93%E9%AA%8C%E6%B5%81%E7%A8%8B-1594380315385.MP4";
//        //音频
//        String video_voice = "https://cdn-school.jikemofang.com/class/audio/531%E5%85%AC%E5%BC%80%E8%AF%BE%E5%81%9A%E8%85%BE%E8%AE%AF%E7%9B%B4%E6%92%AD%E5%A6%82%E4%BD%95%E7%BB%84%E5%BB%BA%E4%B8%87%E4%BA%BA%E5%9B%A2%E9%98%9F%E7%B2%89%E4%B8%9D%E9%94%81%E5%AE%9A%E7%95%99%E5%AD%98-1592815731998.mp3";
//
//        String videoUrl = video_short;
//
//        long start = System.currentTimeMillis();
//        //step1:上传到云点播---处理是异步---到时mq推送
//        //上传云点播采用url拉取上传
//        PullUploadResponse pullUploadResponse = uploadVideoByUrl(videoUrl);
//        Assert.notNull(pullUploadResponse, "视频上传云点播失败");
//        //step2：通过上传成功的任务id---获取任务详情进度---(轮询重试--mq消费支持)
//        DescribeTaskDetailResponse taskDetailResponse = queryTaskProcess(pullUploadResponse.getTaskId(), 1);
//        Assert.notNull(taskDetailResponse.getPullUploadTask(), "视频上传-任务处理返回数据异常");
//        Assert.isTrue(taskDetailResponse.getPullUploadTask().getErrCode() == 0, taskDetailResponse.getPullUploadTask().getMessage());
//        //step3: 视频编辑过程
//        EditMediaFileInfo fileInfo = new EditMediaFileInfo();
//        fileInfo.setFileId(taskDetailResponse.getPullUploadTask().getFileId());
//        fileInfo.setStartTimeOffset(0f);
//        fileInfo.setEndTimeOffset(300f);
//        EditMediaFileInfo[] editMediaFileInfos = {fileInfo};
//        EditMediaResponse editMediaResponse = editVideo(VIDEO_INPUT_TYPE_FILE, editMediaFileInfos, null);
//        Assert.isTrue(editMediaResponse != null, "编辑视频处理 返回为null异常");
//        //step4：编辑之后--异步任务--拉起--到时mq推送
//        DescribeTaskDetailResponse editTaskDetailResponse = queryTaskProcess(editMediaResponse.getTaskId(), 1);
//        log.info("<<<<<<<<<<剪切视频处理，resp={}",JSONObject.toJSONString(editTaskDetailResponse));
//        //防止转码--继续查看任务
//        DescribeTaskDetailResponse editTaskDetailResponseConfirm = queryTaskProcess(editMediaResponse.getTaskId(), 1);
//        log.info("<<<<<<<<<<剪切视频处理,确认查询，resp={}",JSONObject.toJSONString(editTaskDetailResponseConfirm));
//        Assert.isTrue(editTaskDetailResponseConfirm.getEditMediaTask().getErrCode() == 0, editTaskDetailResponseConfirm.getEditMediaTask().getMessage());
//        log.info("<<<<<<<<<<剪切视频处理，共消耗{} ms", System.currentTimeMillis() - start);
//        //step5：编辑任务处理成功后--上传cos
//
//        //step6: 删除媒体操作
//        DeleteMediaResponse deleteMediaResponse = deleteMedia(" 5285890808479220451");
//    }

    /***
     * 递归查询任务进度
     *
     * @param taskId
     * @return
     */
    private static DescribeTaskDetailResponse queryTaskProcess(String taskId, int times) {
        log.info("<<<<第{}次进入", times);
        DescribeTaskDetailResponse taskDetailResponse = queryTaskDetailByUrl(taskId);
        Assert.notNull(taskDetailResponse, "视频上传云点播-查询任务详情失败");
        if (!TASK_STATUS_FINISH.equals(taskDetailResponse.getStatus())) {
            try {
                Thread.sleep(3000L);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            times++;
            queryTaskProcess(taskId, times);
        }
        return taskDetailResponse;
    }


//    public static void main(String[] args) {
//        //获取媒体信息
//        List<String> fileIds = new ArrayList<>();
//        fileIds.add("5285890808511083505");
//        fileIds.add("5285890808511036020");
//        DescribeMediaInfosResponse describeMediaInfosResponse = mediaDetail(fileIds);
//    }
}
